/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analiseSintatica.Regras.DeclaracoesIniciais;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Blocos.RegraDeclsInicial;
import analiseSintatica.Regras.Blocos.RegraDiretivas;
import analiseSintatica.Regras.Regra;
import analiseSintatica.Regras.Tipos.RegraTipoPrimitivo;
import analiseSintatica.Regras.Tipos.RegraStruct;
import analiseSintatica.estruturadados.ErroSintatico;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Dede do Bem
 * 
 * <typedef> ::= typedef (<tipo_primitivo> | <struct>) identificador ";" 
 */
public class RegraTypedef extends Regra {

    protected static Regra instancia;

    protected String estrutura = "typedef (<tipo_primitivo> | <struct>) identificador ';'";
    RegraTipoPrimitivo tipoPrimitivo;
    RegraStruct struct;


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraTypedef() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraTypedef getInstance() {
        if (instancia == null) {
            instancia = new RegraTypedef();
        }
        return (RegraTypedef) instancia;
    }

    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

       ErroSintaticoException erros = new ErroSintaticoException();
        
       NoArvore NaoTerminalTypedf = new NoArvore("<typedef>", false);
       
       NaoTerminalTypedf.adicionaFilho(reconheceLexema(listaTokens,listaTokens.getFirst().getToken(),"typedef",estrutura));

       
       try{
           if(RegraTipoPrimitivo.getInstance().getPrimeiro().contains(listaTokens.getFirst().getLexema())){
               NaoTerminalTypedf.adicionaFilho(RegraTipoPrimitivo.getInstance().analisar(listaTokens));
           }
           else{
               NaoTerminalTypedf.adicionaFilho(RegraStruct.getInstance().analisar(listaTokens));
           }

       }catch(ErroSintaticoException e){

       }

       try{
            NaoTerminalTypedf.adicionaFilho(reconheceToken(listaTokens, "identificador",estrutura));

        }catch(ErroSintaticoException e){

        }

        try{
            NaoTerminalTypedf.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ";",estrutura));
        }catch(ErroSintaticoException e){

        }
             
               System.out.println("Terminei typedef");
       return NaoTerminalTypedf;
        
     }
   
    /**
     * Reconhece terminal "typedef"
     * @param listaTokens - Tokens do codigo
     * @return - Sub-arvore sintatica
     */
    public NoArvore reconheceTypedef(LinkedList<LinkToken> listaTokens) {
        listaTokens.removeFirst();
        return new NoArvore("typedef", true);
    }

    
    
    @Override
    protected void setPrimeiro() {
        this.primeiro.add("typedef");
    }

    @Override
    protected void setSeguinte() {
        this.seguinte.add("void");
        //s(diretivas)     = p(diretivas) U s(decls_inicial)
        //this.seguinte = getUniao(this.seguinte, RegraDeclsInicial.getInstance().getSeguinte());
        //this.seguinte = getUniao(this.seguinte, RegraDiretivas.getInstance().getPrimeiro());
    }
}
